using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Framework;

namespace FrameworkEditor
{
    /// <summary>
    /// singlebg singlebg_lang[包含多语言目录下的]按照内存大小均摊ab设置
    /// singlebg_lang 暂时不处理，资源引用关系有问题
    /// </summary>
    internal class SinglebgAbSettingTool
    {
        public static string singleBgAbCfgPath = FrameworkSettings.ProjRootDir + "/Editor/Settings/singlebgabcfg.json";
        private static string singleBgDir = "Assets/ZResourcesLib/singlebg";
        private static string singleBgLangDir = "Assets/ZResourcesLib/singlebg_lang";
        private static Regex includeRegex = new Regex("(.png|.jpg)$");
        private static Regex ignoreRegex = new Regex("(.meta|.git)$");
        private static long maxMemSize = 2 * 1024 * 1024; //4 MB
        private static Dictionary<string, object> splitPathList;

        public static void RefreshCfg()
        {
            string splitCfgPath = Application.dataPath + "/ZResourcesLib/configs/ressplit.json";
            string jsonStr = FileHelper.ReadText(splitCfgPath).Replace(@"\/", "/");
            jsonStr = FileHelper.GetUnityPath(jsonStr);
            Dictionary<string, object> splitCfg = JsonHelper.DerializeAsDic(jsonStr);
            splitPathList = splitCfg["pathList"] as Dictionary<string, object>;

            Dictionary<string, string[]> abSettings = new Dictionary<string, string[]>();
            GetOneRootDirCfg(singleBgDir, ref abSettings);
            // 多语言目录singlebg_lang资源引用关系暂时存在问题,等大版本的时候，美术处理完再考虑，先不用这个策略
            GetOneRootDirCfg(singleBgLangDir, ref abSettings);
            foreach (var shortcut in LanguageHelper.GetAllLangShortcut())
            {
                if (shortcut.Equals("zh"))
                {
                    continue;
                }
                var langPath = $"Assets/ZResourcesLib/lang/{shortcut}/singlebg_lang";
                if (!FileHelper.IsDirExists(langPath))
                {
                    Debug.LogWarning($"SinglebgAbSettingTool.RefreshCfg, langPath = {langPath} is not exists!");
                    continue;
                }
                GetOneRootDirCfg(langPath, ref abSettings);
            }
            string cfgJson = JsonConvert.SerializeObject(abSettings, Formatting.Indented);
            Debug.Log($"SinglebgAbSettingTool.RefreshCfg, abCount = {abSettings.Count} cfgJson:\n{cfgJson}");
            FileHelper.WriteTextToPath(singleBgAbCfgPath, cfgJson);
        }

        private static void GetOneRootDirCfg(string textureDirPath, ref Dictionary<string, string[]> settingsContainer)
        {
            foreach (var directory in Directory.GetDirectories(textureDirPath, "*.*", SearchOption.TopDirectoryOnly))
            {
                var subSettings = GetOneSubDirCfg(directory);
                foreach (var item in subSettings)
                {
                    settingsContainer.Add(item.Key, item.Value);
                }
            }
        }

        private static bool IsNeedBuild(string filePath, Regex ignoreExtRegex, Regex fileFilter)
        {
            filePath = FileHelper.GetUnityPath(filePath);
            if (ignoreExtRegex.IsMatch(filePath))
            {
                return false;
            }
            if (null != fileFilter && !fileFilter.IsMatch(filePath))
            {
                return false;
            }
            return true;
        }
        private static Dictionary<string, string[]> GetOneSubDirCfg(string subDirPath)
        {
            Dictionary<string, string[]> ret = new Dictionary<string, string[]>();
            string abName = EditorUtils.GetRelativePathToDir(subDirPath, EditorUtils.assetRootDir);
            float packSize = 0f;
            float splitPackSize = 0f;
            List<string> assetNames = new List<string>();
            List<string> splitAssetNames = new List<string>();
            int abIdx = 0;
            foreach (string file in Directory.GetFiles(subDirPath, "*.*", SearchOption.AllDirectories))
            {
                if (!IsNeedBuild(file, ignoreRegex, includeRegex))
                {
                    continue;
                }
                string assetPath = EditorUtils.GetPathRelativeToAssets(file);
                long texStorageSize = EditorUtils.GetTextureStorageSize(assetPath);
                if (0 == texStorageSize)
                {
                    Debug.LogError($"GetOneSubDirCfg error: file = {file} assetPatha = {assetPath}");
                    continue;
                }
                bool isSplitFile = splitPathList.ContainsKey(assetPath.Replace("Assets/ZResourcesLib/", ""));
                if (isSplitFile)
                {
                    splitPackSize += texStorageSize;
                    splitAssetNames.Add(assetPath);
                    if (splitPackSize > maxMemSize)
                    {
                        ret.Add(abName + "" + abIdx, splitAssetNames.ToArray());
                        splitPackSize = 0;
                        splitAssetNames.Clear();
                        abIdx++;
                    }
                }
                else
                {
                    packSize += texStorageSize;
                    assetNames.Add(assetPath);
                    if (packSize > maxMemSize)
                    {
                        ret.Add(abName + "" + abIdx, assetNames.ToArray());
                        packSize = 0;
                        assetNames.Clear();
                        abIdx++;
                    }
                }
            }
            if (assetNames.Count > 0)
            {
                ret.Add(abName + "" + abIdx, assetNames.ToArray());
                assetNames.Clear();
                abIdx++;
            }
            if (splitAssetNames.Count > 0)
            {
                ret.Add(abName + "" + abIdx, splitAssetNames.ToArray());
                splitAssetNames.Clear();
                abIdx++;
            }
            return ret;
        }
    }
}